//
//  LYQStatusListViewModel.swift
//  SwiftWeibo
//
//  Created by 刘英群 on 2017/1/5.
//  Copyright © 2017年 刘英群. All rights reserved.
//

import Foundation
import SDWebImage

//weibo数据列表视图模型
/*
 父类的选择
 - 如果类需要使用‘KVC’或者字典转模型框架设置对象的值，类就需要继承自NSObject
 - 如果类知识包装了一些代码逻辑（写了一些函数）， 可以不用任何父类， 好处：更加轻量级
 - 提示： 如果用OC写， 一律都继承自NSObject即可
 
 使命： 负责微博的数据处理
 1. 字典转模型
 2. 下拉 上拉 刷新数据处理
 */

//上拉刷新最大尝试次数
fileprivate let maxPullupTryTimes = 3

class LYQStatusListViewModel {
    
    //微博视图模型数组懒加载
    lazy var statusList = [LYQStatusViewModel]()
    
    // 上拉刷新错误次数
    private var pullupErrorTimes = 0
    
    
    ///加载微博列表
    /// - Parameter pullup    : 是否上拉刷新标记
    /// - Parameter completion: 完成回调[网络请求是否成功,是否刷新表格]
    func loadStatus(pullup: Bool, completion: @escaping (_ isSuccess: Bool, _ shouldRefresh: Bool)->()) {
        
        // 判断是否是上拉刷新，同时检测刷新错误
        if pullup && pullupErrorTimes > maxPullupTryTimes {
            
            completion(true, false)
            return
        }
        
        //since_id 取出数组中第一条微博的id
        let since_id = pullup ? 0 : (statusList.first?.status.id ?? 0)
        
        let max_id = !pullup ? 0 : (statusList.last?.status.id ?? 0)
        
        // 发起网络请求，加载微博数据（字典数组）
        LYQNetworkManager.shared.statusList(since_id: since_id, max_id: max_id) { (list, isSuccess) in
            
            // 如果网络请求失败直接返回,直接执行完成回调
            if !isSuccess {
                
                completion(false, false)
                return
            }
            
            // 遍历字典数组，字典转模型 => 视图模型，将视图模型添加到数组
            var array = [LYQStatusViewModel]()
            
            for dict in list ?? [] {
                
//                print(dict["pic_urls"])
                // 1.创建微博模型
                let status = LYQStatus()
                
                // 2.使用字典设置模型数值
                status.yy_modelSet(with: dict)
                
                // 3.使用‘微博’模型创建‘微博视图’模型
                let viewModel = LYQStatusViewModel(model: status)
                
                //4.添加到数组
                array.append(viewModel)
            }
            
            //视图模型创建完成
            print(array)
            
            
            print("刷新到\(array.count)条数据\(array)")
            
            //2.拼接数据
            
            if pullup {
                //上啦刷新结束后，结果拼在数组末尾
                self.statusList += array
            } else {
                //下拉刷新，应该将结果数组拼接在数组前面
                self.statusList = array + self.statusList
            }
            
            //3.判断上拉刷新的数据量
            if pullup && array.count == 0 {
                
                self.pullupErrorTimes += 1
                completion(isSuccess, false)
            }else{
                
                self.cacheSingleImage(list: array, completion: completion)
                //4.完成回调 真正有数据的回调
                //
//                completion(isSuccess, true)
            }
        }
    }
    
    
    /// 缓存本次下载微博数据数组中的单张图像，多张图像不用缓存，多张图像用的是九宫格缓存
    
    /// - 应该缓存完单张图像，并且修改过配图的大小之后，再回调，才能够保证表格等比例显示单张图像
    ///
    /// - Parameter list: 本次下载的视图模型数组
    fileprivate func cacheSingleImage(list: [LYQStatusViewModel], completion: @escaping (_ isSuccess: Bool, _ shouldRefresh: Bool)->()) {
        
        //GCD调度组
        let group = DispatchGroup()
        
        //记录数据长度
        var length = 0

        //遍历数组， 查找微博数据中有单张图像的， 进行缓存，多张不需要缓存
        // option + com + 左 折叠代码
        for vm in list {
            
            //1. 判断图像数量
            if vm.picURLs?.count != 1 {
                
                continue
            }
            
            // 2.代码执行到此，数组中有且仅有一张图片，就可以强行解包
            guard let pic = vm.picURLs![0].thumbnail_pic,
                let url = URL(string: pic) else {
                    
                    continue
            }
            
            
//            print("要缓存的图片是\(url)")
            
            // 3.下载图像
            // downloadImage 是 sdwebimage的 核心方法
            // 图像下载完成之后， 会自动保存在沙盒中， 文件路径是url的md5
            // 如果沙盒中已经存在缓存的图像，后续使用SD通过URL加载图像，都会加载本地沙盒的图像
            // 不会发起网络请求，同时，回调方法，同样会调用
            // 内部不会再次发起网络请求
            // *** 注意：如果要缓存的图像累计很大，要找后台要接口
            
            // a> 入组
            group.enter()
            
            SDWebImageManager.shared().downloadImage(with: url, options: [], progress: nil, completed: { (image, _, _, _, _) in
                
                
                // 将图像转换成二进制数据
                if let image = image,
                    let data = UIImagePNGRepresentation(image) {
                    
                    //NSData 是 length 属性
                    length += data.count
                    
                    // 图像缓存成功，更新配图视图的大小
                    vm.updateSingleImageSize(image: image)
                }
                print("缓存的图像是\(image) 长度\(length)")
                
                //b> 出组 - 放在回调的最后一句
                group.leave()
            })
        }
        
        // C> 监听调度组情况
        group.notify(queue: DispatchQueue.main) {
            
            print("图像缓存完成 \(length / 1024) K")
            
            //执行闭包回调
            completion(true, true)
        }
    }
}
